/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ejbs;

import entities.Almacen;
import entities.FacturaPedidoFabrica;
import entities.LineaFacturaPedidoFabrica;
import entities.LineaInventarioAlmacen;
import entities.LineaTicket;
import entities.ProductoTalla;
import entities.Ticket;
import entities.TicketFormaPago;
import facades.AlmacenFacade;
import facades.LineaInventarioAlmacenFacade;
import facades.LineaTicketFacade;
import facades.TicketFacade;
import facades.TicketFormaPagoFacade;
import facades.TipoTicketFacade;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.ejb.Stateless;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import pos.qualifiers.EventoLineaTicketReservaCreada;
import pos.qualifiers.EventoPreCrearLineaTicketReserva;
import qualifiers.EventoEntidadBorrada;
import qualifiers.EventoEntidadCreada;
import qualifiers.EventoEntidadEditada;
import qualifiers.EventoPreBorrarEntidad;
import qualifiers.EventoPreCrearEntidad;
import qualifiers.EventoPreEditarEntidad;

/**
 *
 * @author damfercer
 */
@Stateless
public class InventarioEJB {
    @Inject
    private TipoTicketFacade tipoTicketFacade;
    @Inject
    private TicketFormaPagoFacade ticketFormaPagoFacade;
    @Inject
    private TicketFacade ticketFacade;
    @Inject
    private LineaTicketFacade lineaTicketFacade;
    @Inject
    private LineaInventarioAlmacenFacade lineaInventarioFacade;
    @Inject
    private AlmacenFacade almacenFacade;
    @Inject
    @EventoPreCrearEntidad
    private Event<LineaInventarioAlmacen> eventoPreCrearLineaInventario;
    @Inject
    @EventoEntidadCreada
    private Event<LineaInventarioAlmacen> eventoLineaInventarioCreada;
    @Inject
    @EventoPreEditarEntidad
    private Event<LineaInventarioAlmacen> eventoPreEditarLineaInventario;
    @Inject
    @EventoEntidadEditada
    private Event<LineaInventarioAlmacen> eventoLineaInventarioEditada;
    @Inject
    @EventoPreBorrarEntidad
    private Event<LineaInventarioAlmacen> eventoPreBorrarLineaInventario;
    @Inject
    @EventoEntidadBorrada
    private Event<LineaInventarioAlmacen> eventoLineaInventarioBorrada;
    @Inject
    @EventoEntidadEditada
    private Event<Almacen> eventoAlmacenEditado;
    @Inject
    @EventoEntidadCreada
    private Event<Ticket> eventoTicketCreada;
    @Inject
    @EventoPreCrearEntidad
    private Event<LineaTicket> eventoPreCrearLineaTicket;
    @Inject
    @EventoEntidadCreada
    private Event<LineaTicket> eventoLineaTicketCreada;
    @Inject
    @EventoPreCrearLineaTicketReserva
    private Event<LineaTicket> eventoPreCrearLineaTicketReserva;
    @Inject
    @EventoLineaTicketReservaCreada
    private Event<LineaTicket> eventoLineaTicketReservaCreada;
    
    private void refrescarAlmacen(Almacen almacen){
        eventoAlmacenEditado.fire(almacen);
        almacenFacade.evict(almacen,almacen.getIdAlmacen());
    }
    
    public void onNuevaLineaTicket(@Observes @EventoEntidadCreada LineaTicket lineaTicket){
        Map<ProductoTalla,Integer> map=new HashMap<ProductoTalla, Integer>();
        map.put(lineaTicket.getProductoTalla(), lineaTicket.getCantidad());
        List<Almacen> almacenes=new ArrayList<Almacen>();
        almacenes.add(lineaTicket.getAlmacen());
        if(lineaTicket.getCantidad()>=0){
            restarCantidadInventario(map, almacenes);
        }
        else{
            map.put(lineaTicket.getProductoTalla(), lineaTicket.getCantidad()*(-1));
            addCantidadInventario(map, almacenes);
        }
    }
    
    public void restarCantidadInventario(Map<ProductoTalla,Integer> productoTallaCantidadARestar, List<Almacen> almacenesAAplicar){
        for (Almacen almacen : almacenesAAplicar) {
            for (Map.Entry<ProductoTalla, Integer> entry : productoTallaCantidadARestar.entrySet()) {
                ProductoTalla productoTalla = entry.getKey();
                Integer cantidad = entry.getValue();
                LineaInventarioAlmacen lineaInventario=lineaInventarioFacade.getLineaInventarioDeAlmacen(almacen, productoTalla);
                if(lineaInventario==null){
                    lineaInventario=new LineaInventarioAlmacen();
                    lineaInventario.setAlmacen(almacen);
                    lineaInventario.setCantidad(0-cantidad);
                    lineaInventario.setProductoTalla(productoTalla);
                    eventoPreCrearLineaInventario.fire(lineaInventario);
                    lineaInventarioFacade.create(lineaInventario);
                    if(almacen.getLineaInventarioAlmacenList()==null){
                        almacen.setLineaInventarioAlmacenList(new ArrayList<LineaInventarioAlmacen>());
                    }
                    almacen.getLineaInventarioAlmacenList().add(lineaInventario);
                    lineaInventario.setAlmacen(almacen);
                    eventoLineaInventarioCreada.fire(lineaInventario);
                    lineaInventarioFacade.evict(lineaInventario, lineaInventario.getIdLineaInventarioAlmacen());
                }
                else{
                    lineaInventario.setCantidad(lineaInventario.getCantidad()-cantidad);
                    if(lineaInventario.getCantidad()==0){
                        eventoPreBorrarLineaInventario.fire(lineaInventario);
                        lineaInventarioFacade.remove(lineaInventario);
                        almacen.getLineaInventarioAlmacenList().remove(lineaInventario);
                        eventoLineaInventarioBorrada.fire(lineaInventario);
                        lineaInventarioFacade.evict(lineaInventario, lineaInventario.getIdLineaInventarioAlmacen());
                    }
                    else{
                        eventoPreEditarLineaInventario.fire(lineaInventario);
                        lineaInventarioFacade.edit(lineaInventario);
                        Collections.replaceAll(almacen.getLineaInventarioAlmacenList(), lineaInventario, lineaInventario);
                        lineaInventario.setAlmacen(almacen);
                        eventoLineaInventarioEditada.fire(lineaInventario);
                        lineaInventarioFacade.evict(lineaInventario, lineaInventario.getIdLineaInventarioAlmacen());
                    }
                }
            }
            refrescarAlmacen(almacen);
        }
    }
    
    public void addCantidadInventario(Map<ProductoTalla,Integer> productoTallaCantidadARestar, List<Almacen> almacenesAAplicar){
        for (Almacen almacen : almacenesAAplicar) {
            for (Map.Entry<ProductoTalla, Integer> entry : productoTallaCantidadARestar.entrySet()) {
                ProductoTalla productoTalla = entry.getKey();
                Integer cantidad = entry.getValue();
                LineaInventarioAlmacen lineaInventario=lineaInventarioFacade.getLineaInventarioDeAlmacen(almacen, productoTalla);
                if(lineaInventario==null){
                    lineaInventario=new LineaInventarioAlmacen();
                    lineaInventario.setAlmacen(almacen);
                    lineaInventario.setCantidad(cantidad);
                    lineaInventario.setProductoTalla(productoTalla);
                    eventoPreCrearLineaInventario.fire(lineaInventario);
                    lineaInventarioFacade.create(lineaInventario);
                    if(almacen.getLineaInventarioAlmacenList()==null){
                        almacen.setLineaInventarioAlmacenList(new ArrayList<LineaInventarioAlmacen>());
                    }
                    almacen.getLineaInventarioAlmacenList().add(lineaInventario);
                    lineaInventario.setAlmacen(almacen);
                    eventoLineaInventarioCreada.fire(lineaInventario);
                    lineaInventarioFacade.evict(lineaInventario, lineaInventario.getIdLineaInventarioAlmacen());
                }
                else{
                    lineaInventario.setCantidad(lineaInventario.getCantidad()+cantidad);
                    if(lineaInventario.getCantidad()==0){
                        eventoPreBorrarLineaInventario.fire(lineaInventario);
                        lineaInventarioFacade.remove(lineaInventario);
                        almacen.getLineaInventarioAlmacenList().remove(lineaInventario);
                        eventoLineaInventarioBorrada.fire(lineaInventario);
                        lineaInventarioFacade.evict(lineaInventario, lineaInventario.getIdLineaInventarioAlmacen());
                    }
                    else{
                        eventoPreEditarLineaInventario.fire(lineaInventario);
                        lineaInventarioFacade.edit(lineaInventario);
                        Collections.replaceAll(almacen.getLineaInventarioAlmacenList(), lineaInventario, lineaInventario);
                        lineaInventario.setAlmacen(almacen);
                        eventoLineaInventarioEditada.fire(lineaInventario);
                        lineaInventarioFacade.evict(lineaInventario, lineaInventario.getIdLineaInventarioAlmacen());
                    }
                }
            }
            refrescarAlmacen(almacen);
        }
    }
    
    public void onPreCrearTicket(@Observes @EventoPreCrearEntidad Ticket ticket){
        List<TicketFormaPago> ticketsFormaPago=ticket.getTicketFormaPagoList();
        ticket.setTicketFormaPagoList(null);
        List<LineaTicket> lineasTicket=ticket.getLineaTicketList();
        ticket.setLineaTicketList(null);
        ticket.setFecha(new Date());
        ticket.setIdentificador(UUID.randomUUID().getMostSignificantBits());
        ticketFacade.create(ticket);
        for (LineaTicket lineaTicket : lineasTicket) {
            if(lineaTicket.getCantidad()!=0){
               lineaTicket.setTicket(ticket);
                if(!ticket.getTipoTicket().equals(tipoTicketFacade.getTipoTicketReserva())){
                    eventoPreCrearLineaTicket.fire(lineaTicket);
                }
                else{
                    eventoPreCrearLineaTicketReserva.fire(lineaTicket);
                }
                lineaTicketFacade.create(lineaTicket);
                if(ticket.getLineaTicketList()==null){
                    ticket.setLineaTicketList(new ArrayList<LineaTicket>());
                }
                ticket.getLineaTicketList().add(lineaTicket);
                if(!ticket.getTipoTicket().equals(tipoTicketFacade.getTipoTicketReserva())){
                    eventoLineaTicketCreada.fire(lineaTicket);
                }
                else{
                    eventoLineaTicketReservaCreada.fire(lineaTicket);
                }
                lineaTicketFacade.evict(lineaTicket, lineaTicket.getIdLineaTicket()); 
            }
            
        }
        for (TicketFormaPago ticketFormaPago : ticketsFormaPago) {
            ticketFormaPago.setTicket(ticket);
            ticketFormaPagoFacade.create(ticketFormaPago);
            if(ticket.getTicketFormaPagoList()==null){
                ticket.setTicketFormaPagoList(new ArrayList<TicketFormaPago>());
            }
            ticket.getTicketFormaPagoList().add(ticketFormaPago);
        }
        ticketFacade.evict(ticket, ticket.getIdTicket());
        eventoTicketCreada.fire(ticket);
    }
            
    public void onNuevaRecepcionPedidoFabrica(@Observes @EventoEntidadCreada FacturaPedidoFabrica facturaPedidoFabrica){
        if(facturaPedidoFabrica.getAlmacen()!=null && facturaPedidoFabrica.getLineaFacturaPedidoFabricaList()!=null){
            List<Almacen> almacenesAdd=new ArrayList<Almacen>();
            Map<ProductoTalla,Integer> productoTallaCantidadMap=new HashMap<ProductoTalla, Integer>();
            almacenesAdd.add(facturaPedidoFabrica.getAlmacen());
            for (LineaFacturaPedidoFabrica lineaFactura : facturaPedidoFabrica.getLineaFacturaPedidoFabricaList()) {
                productoTallaCantidadMap.put(lineaFactura.getProductoTalla(), lineaFactura.getCantidad());
            }
            addCantidadInventario(productoTallaCantidadMap, almacenesAdd);
        }
        //almacenFacade.evict(facturaPedidoFabrica.getAlmacen(), facturaPedidoFabrica.getAlmacen().getIdAlmacen());
    }
}
